In [68]:
def multimax(iterable, key=None):
    """
    Function that takes an iterable and returns all
    maximum values found in the iterable
    """
    input = list(iterable)
    if key:
        return [it for it in input if key(it) == key(max(input, key=key))]
    return [it for it in input if it == max(input)]

In [69]:
multimax([1, 2, 4, 3])


Out[69]:
[4]

In [70]:
multimax([1, 4, 2, 4, 3])


Out[70]:
[4, 4]

In [71]:
multimax([1, 1, 1])


Out[71]:
[1, 1, 1]

Bonus1: Make sure the function returns an empty list if the iterable is empty


In [72]:
multimax([])


Out[72]:
[]

Bonus2: Make sure the function works well with iterator such as files, generators etc


In [73]:
numbers = [1, 3, 8, 5, 4, 10, 6]
odds = (n for n in numbers if n % 2 == 1)
multimax(odds)


Out[73]:
[5]

Bonus3: The multimax function accept a keyword argument called "key" that is a function which will be used to determine the key by which to compare values as maximums. For example the key function could be used to find the longest words in a list of words


In [74]:
words = ["cheese", "shop", "ministry", "of", "silly", "walks", "argument", "clinic"]

In [75]:
multimax(words, key=len)


Out[75]:
['ministry', 'argument']

In [80]:
words = ["cheese", "shop", "ministry", "of", "silly", "walks", "argument", "clinic"]
max(words, key=len)


Out[80]:
'ministry'

In [79]:
words = ["cheese", "shop", "argument", "of", "silly", "walks", "ministry", "clinic"]
max(words, key=len)


Out[79]:
'argument'

Unitests


In [78]:
import unittest


class MultiMaxTests(unittest.TestCase):

    """Tests for multimax."""

    def test_single_max(self):
        self.assertEqual(multimax([1, 2, 4, 3]), [4])

    def test_two_max(self):
        self.assertEqual(multimax([1, 4, 2, 4, 3]), [4, 4])

    def test_all_max(self):
        self.assertEqual(multimax([1, 1, 1, 1, 1]), [1, 1, 1, 1, 1])

    def test_lists(self):
        inputs = [[0], [1], [], [0, 1], [1]]
        expected = [[1], [1]]
        self.assertEqual(multimax(inputs), expected)

    def test_order_maintained(self):
        inputs = [
            (3, 2),
            (2, 1),
            (3, 2),
            (2, 0),
            (3, 2),
        ]
        expected = [
            inputs[0],
            inputs[2],
            inputs[4],
        ]
        outputs = multimax(inputs)
        self.assertEqual(outputs, expected)
        self.assertIs(outputs[0], expected[0])
        self.assertIs(outputs[1], expected[1])
        self.assertIs(outputs[2], expected[2])

    # To test the Bonus part of this exercise, comment out the following line
    # @unittest.expectedFailure
    def test_empty(self):
        self.assertEqual(multimax([]), [])

    # To test the Bonus part of this exercise, comment out the following line
    # @unittest.expectedFailure
    def test_iterator(self):
        numbers = [1, 4, 2, 4, 3]
        squares = (n**2 for n in numbers)
        self.assertEqual(multimax(squares), [16, 16])

    # To test the Bonus part of this exercise, comment out the following line
    # @unittest.expectedFailure
    def test_key_function(self):
        words = ["alligator", "animal", "apple", "artichoke", "avalanche"]
        outputs = ["alligator", "artichoke", "avalanche"]
        self.assertEqual(multimax(words, key=len), outputs)


if __name__ == "__main__":
    unittest.main(argv=['first-arg-is-ignored'], exit=False)


........
----------------------------------------------------------------------
Ran 8 tests in 0.004s

OK

In [ ]:


In [ ]: